[HVM] Provide common support function for HLT emulation: hvm_hlt().
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Wed, 16 Aug 2006 13:27:30 +0000 (14:27 +0100)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Wed, 16 Aug 2006 13:27:30 +0000 (14:27 +0100)
Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/hvm/hvm.c
xen/arch/x86/hvm/svm/svm.c
xen/arch/x86/hvm/svm/vmcb.c
xen/arch/x86/hvm/vmx/vmcs.c
xen/arch/x86/hvm/vmx/vmx.c
xen/include/asm-x86/hvm/support.h
xen/include/asm-x86/hvm/svm/vmcb.h
xen/include/asm-x86/hvm/vcpu.h
xen/include/asm-x86/hvm/vmx/vmcs.h

index 6c254e2a61b21643ad6ff841928c03da4f27e4c1..fd4b69423b5c3cde0eef0005e2d42bc05e580ade 100644 (file)
@@ -345,6 +345,36 @@ int cpu_get_interrupt(struct vcpu *v, int *type)
     return -1;
 }
 
+void hvm_hlt(unsigned long rflags)
+{
+    struct vcpu *v = current;
+    struct periodic_time *pt = &v->domain->arch.hvm_domain.pl_time.periodic_tm;
+    s_time_t next_pit = -1, next_wakeup;
+
+    /*
+     * Detect machine shutdown.  Only do this for vcpu 0, to avoid potentially 
+     * shutting down the domain early. If we halt with interrupts disabled, 
+     * that's a pretty sure sign that we want to shut down.  In a real 
+     * processor, NMIs are the only way to break out of this.
+     */
+    if ( (v->vcpu_id == 0) && !(rflags & X86_EFLAGS_IF) )
+    {
+        printk("D%d: HLT with interrupts enabled -- shutting down.\n",
+               current->domain->domain_id);
+        domain_shutdown(current->domain, SHUTDOWN_poweroff);
+        return;
+    }
+
+    if ( !v->vcpu_id )
+        next_pit = get_scheduled(v, pt->irq, pt);
+    next_wakeup = get_apictime_scheduled(v);
+    if ( (next_pit != -1 && next_pit < next_wakeup) || next_wakeup == -1 )
+        next_wakeup = next_pit;
+    if ( next_wakeup != - 1 ) 
+        set_timer(&current->arch.hvm_vcpu.hlt_timer, next_wakeup);
+    do_sched_op_compat(SCHEDOP_block, 0);
+}
+
 /*
  * Copy from/to guest virtual.
  */
index e971f272e5e7ef1c76f59366f653a9070e7cf666..f7ae00937eb2c6afdbb9d9c6101033cf59ff857b 100644 (file)
@@ -835,7 +835,7 @@ static void svm_relinquish_guest_resources(struct domain *d)
 
         destroy_vmcb(&v->arch.hvm_svm);
         free_monitor_pagetable(v);
-        kill_timer(&v->arch.hvm_svm.hlt_timer);
+        kill_timer(&v->arch.hvm_vcpu.hlt_timer);
         if ( hvm_apic_support(v->domain) && (VLAPIC(v) != NULL) ) 
         {
             kill_timer( &(VLAPIC(v)->vlapic_timer) );
@@ -863,7 +863,7 @@ static void svm_migrate_timers(struct vcpu *v)
 
     if ( pt->enabled ) {
         migrate_timer( &pt->timer, v->processor );
-        migrate_timer( &v->arch.hvm_svm.hlt_timer, v->processor );
+        migrate_timer( &v->arch.hvm_vcpu.hlt_timer, v->processor );
     }
     if ( hvm_apic_support(v->domain) && VLAPIC( v ))
         migrate_timer( &(VLAPIC(v)->vlapic_timer ), v->processor );
@@ -2144,47 +2144,16 @@ done:
 }
 
 
-/*
- * Need to use this exit to reschedule
- */
 static inline void svm_vmexit_do_hlt(struct vmcb_struct *vmcb)
 {
-    struct vcpu *v = current;
-    struct periodic_time *pt = 
-        &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
-    s_time_t next_pit = -1, next_wakeup;
-
     __update_guest_eip(vmcb, 1);
 
-    /* check for interrupt not handled or new interrupt */
-    if ( vmcb->vintr.fields.irq || cpu_has_pending_irq(v) )
+    /* Check for interrupt not handled or new interrupt. */
+    if ( (vmcb->rflags & X86_EFLAGS_IF) &&
+         (vmcb->vintr.fields.irq || cpu_has_pending_irq(current)) )
        return;
 
-    /* Detect machine shutdown.  Only do this for vcpu 0, to avoid
-       potentially shutting down the domain early. */
-    if (v->vcpu_id == 0) {
-        unsigned long rflags = vmcb->rflags; 
-        /* If we halt with interrupts disabled, that's a pretty sure
-           sign that we want to shut down.  In a real processor, NMIs
-           are the only way to break out of this.  Our SVM code won't
-           deliver interrupts, but will wake it up whenever one is
-           pending... */
-        if(!(rflags & X86_EFLAGS_IF)) {
-            printk("D%d: HLT with interrupts enabled @0x%lx  Shutting down.\n",
-                   current->domain->domain_id, (unsigned long)vmcb->rip);
-            domain_shutdown(current->domain, SHUTDOWN_poweroff);
-            return;
-        }
-    }
-
-    if ( !v->vcpu_id )
-        next_pit = get_scheduled(v, pt->irq, pt);
-    next_wakeup = get_apictime_scheduled(v);
-    if ( (next_pit != -1 && next_pit < next_wakeup) || next_wakeup == -1 )
-        next_wakeup = next_pit;
-    if ( next_wakeup != - 1 )
-        set_timer(&current->arch.hvm_svm.hlt_timer, next_wakeup);
-    do_sched_op_compat(SCHEDOP_block, 0);
+    hvm_hlt(vmcb->rflags);
 }
 
 
index 6ed5a6ab9425ab4ad90b8a2bd89ab9084a54a89a..349381e3ecc82abcc28dcee382ddb9966c33c881 100644 (file)
@@ -360,8 +360,7 @@ void svm_do_launch(struct vcpu *v)
 
     if (hvm_apic_support(v->domain))
         vlapic_init(v);
-    init_timer(&v->arch.hvm_svm.hlt_timer,
-                               hlt_timer_fn, v, v->processor);
+    init_timer(&v->arch.hvm_vcpu.hlt_timer, hlt_timer_fn, v, v->processor);
 
     vmcb->ldtr.sel = 0;
     vmcb->ldtr.base = 0;
index 288c2ac03430fe6e3ebe06e9639c3927e078fa41..ebd8a42f6876e89e4c8b49581140eb4d4d1e93ad 100644 (file)
@@ -267,7 +267,7 @@ static void vmx_do_launch(struct vcpu *v)
         vlapic_init(v);
 
     vmx_set_host_env(v);
-    init_timer(&v->arch.hvm_vmx.hlt_timer, hlt_timer_fn, v, v->processor);
+    init_timer(&v->arch.hvm_vcpu.hlt_timer, hlt_timer_fn, v, v->processor);
 
     error |= __vmwrite(GUEST_LDTR_SELECTOR, 0);
     error |= __vmwrite(GUEST_LDTR_BASE, 0);
index ea52efdb33c46c67fd9d52e24484ef914d2fbeb7..658ee8ae73524908561c71d93faef4d183f273b6 100644 (file)
@@ -134,7 +134,7 @@ static void vmx_relinquish_guest_resources(struct domain *d)
         if ( !test_bit(_VCPUF_initialised, &v->vcpu_flags) )
             continue;
         free_monitor_pagetable(v);
-        kill_timer(&v->arch.hvm_vmx.hlt_timer);
+        kill_timer(&v->arch.hvm_vcpu.hlt_timer);
         if ( hvm_apic_support(v->domain) && (VLAPIC(v) != NULL) )
         {
             kill_timer(&VLAPIC(v)->vlapic_timer);
@@ -496,7 +496,7 @@ void vmx_migrate_timers(struct vcpu *v)
 
     if ( pt->enabled ) {
         migrate_timer(&pt->timer, v->processor);
-        migrate_timer(&v->arch.hvm_vmx.hlt_timer, v->processor);
+        migrate_timer(&v->arch.hvm_vcpu.hlt_timer, v->processor);
     }
     if ( hvm_apic_support(v->domain) && VLAPIC(v))
         migrate_timer(&(VLAPIC(v)->vlapic_timer), v->processor);
@@ -2049,46 +2049,11 @@ static inline void vmx_do_msr_write(struct cpu_user_regs *regs)
                 (unsigned long)regs->edx);
 }
 
-/*
- * Need to use this exit to reschedule
- */
 void vmx_vmexit_do_hlt(void)
 {
-    struct vcpu *v = current;
-    struct periodic_time *pt = 
-        &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
-    s_time_t next_pit = -1, next_wakeup;
-
-
-    /* Detect machine shutdown.  Only do this for vcpu 0, to avoid
-       potentially shutting down the domain early. */
-    if (v->vcpu_id == 0) {
-        unsigned long rflags;
-        
-        __vmread(GUEST_RFLAGS, &rflags);
-        /* If we halt with interrupts disabled, that's a pretty sure
-           sign that we want to shut down.  In a real processor, NMIs
-           are the only way to break out of this.  Our VMX code won't
-           deliver interrupts, but will wake it up whenever one is
-           pending... */
-        if(!(rflags & X86_EFLAGS_IF)) {
-            unsigned long rip;
-            __vmread(GUEST_RIP, &rip);
-            printk("D%d: HLT with interrupts enabled @0x%lx  Shutting down.\n",
-                   current->domain->domain_id, rip);
-            domain_shutdown(current->domain, SHUTDOWN_poweroff);
-            return;
-        }
-    }
-
-    if ( !v->vcpu_id )
-        next_pit = get_scheduled(v, pt->irq, pt);
-    next_wakeup = get_apictime_scheduled(v);
-    if ( (next_pit != -1 && next_pit < next_wakeup) || next_wakeup == -1 )
-        next_wakeup = next_pit;
-    if ( next_wakeup != - 1 ) 
-        set_timer(&current->arch.hvm_vmx.hlt_timer, next_wakeup);
-    do_sched_op_compat(SCHEDOP_block, 0);
+    unsigned long rflags;
+    __vmread(GUEST_RFLAGS, &rflags);
+    hvm_hlt(rflags);
 }
 
 static inline void vmx_vmexit_do_extint(struct cpu_user_regs *regs)
index d4adb1b6cb8c97ef3b852b04147a3ecbe76a6336..35a0bfe4644ef8af611c3a0b814676d8e1def9bc 100644 (file)
@@ -148,4 +148,6 @@ void hvm_do_hypercall(struct cpu_user_regs *pregs);
 
 void hvm_prod_vcpu(struct vcpu *v);
 
+void hvm_hlt(unsigned long rflags);
+
 #endif /* __ASM_X86_HVM_SUPPORT_H__ */
index 7d227f77c5c92b3edc6d1c57b9b18c9fb476f699..58a683b06e5e1201dde02dee0e775cf639a52425 100644 (file)
@@ -448,7 +448,6 @@ struct arch_svm_struct {
     unsigned long       cpu_cr2;
     unsigned long       cpu_cr3;
     unsigned long       cpu_state;
-    struct timer        hlt_timer;  /* hlt ins emulation wakeup timer */
 };
 
 extern struct vmcb_struct *alloc_vmcb(void);
index f5e2249398fda92d7c5b5dd7be4eae97fee2891a..f89b6ad7870a415f97b29bc9eb935517ec2474e3 100644 (file)
@@ -43,15 +43,18 @@ struct hvm_vcpu {
     /* Flags */
     int                 flag_dr_dirty;
 
+    /* hlt ins emulation wakeup timer */
+    struct timer        hlt_timer;
+
     union {
         struct arch_vmx_struct vmx;
         struct arch_svm_struct svm;
     } u;
 };
 
-#define ARCH_HVM_IO_WAIT            1   /* Waiting for I/O completion */
+#define ARCH_HVM_IO_WAIT         1   /* Waiting for I/O completion */
 
-#define HVM_CONTEXT_STACK_BYTES     (offsetof(struct cpu_user_regs, error_code))
+#define HVM_CONTEXT_STACK_BYTES  (offsetof(struct cpu_user_regs, error_code))
 
 #endif /* __ASM_X86_HVM_VCPU_H__ */
 
index 433bcd2e91984805494d8d59204d4a792322770a..85ee7046fd478619b64940dfa84da884567c9592 100644 (file)
@@ -93,7 +93,6 @@ struct arch_vmx_struct {
     unsigned long        cpu_based_exec_control;
     struct vmx_msr_state msr_content;
     void                *io_bitmap_a, *io_bitmap_b;
-    struct timer         hlt_timer;  /* hlt ins emulation wakeup timer */
 };
 
 #define vmx_schedule_tail(next)         \